package co.dreamapps.dodoattack.model;

import java.io.IOException;
import java.util.Collection;

import org.andengine.audio.sound.Sound;
import org.andengine.audio.sound.SoundFactory;
import org.andengine.engine.Engine;
import org.andengine.entity.IEntity;
import org.andengine.entity.modifier.IEntityModifier.IEntityModifierListener;
import org.andengine.entity.modifier.MoveModifier;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.opengl.texture.TextureManager;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.ITiledTextureRegion;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.util.modifier.IModifier;

import co.dreamapps.dodoattack.activities.GameActivity;
import android.content.Context;

public class Egg implements IEntityModifierListener {	

	/**
	 * Private constants
	 */
	private static final long[] CRASH_DURATION_FRAMES = { 60, 120, 120, 40, 50, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60 };
	private static final int CRASH_START_INDEX = 7;
	private static final int CRASH_END_INDEX = 21;
	private final float COLLIDE_DISTANCE = 80;

	final float ON_AIR_DURATION = 2.5f;

	/**
	 * Window parameters
	 */
	private static int windowWidth, windowHeight;

	/**
	 * Configuration
	 */
	public int eggId;

	/**
	 * Animation
	 */
	private static ITiledTextureRegion texturaAnimada;
	private static BitmapTextureAtlas atlasAnimacion;
	private AnimatedSprite spriteAnimado;
	private GameActivity game;
	private Scene scene;
	private Collection<Egg> eggs;

	/**
	 * Modifiers
	 */
	private MoveModifier moveModifier;

	/**
	 * Sound
	 */
	private static Sound eggSound;

	/**
	 * Connection
	 */
	private RoomManagerDodoGame roomManager;
	private boolean isCreator;

	/**
	 * Constructor
	 */
	public Egg(GameActivity game, RoomManagerDodoGame roomManager, boolean isCreator, int eggId, Collection<Egg> eggs) {
		this.game = game;
		this.roomManager = roomManager;
		this.isCreator = isCreator;
		this.eggId = eggId;
		this.eggs = eggs;
	}

	/**
	 * Static import of resources
	 */
	public static void onCreateResources(TextureManager textureManager, Engine engine, Context context, int windowWidth, int windowHeight) throws IOException {
		atlasAnimacion = new BitmapTextureAtlas(textureManager, 290, 430,TextureOptions.DEFAULT);
		texturaAnimada = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(atlasAnimacion, context,"eggSecuencia.png", 0, 0, 4, 6);
		atlasAnimacion.load();
		try {
			eggSound = SoundFactory.createSoundFromAsset(engine.getSoundManager(), context, "sonido/eggCrash.mp3");
			eggSound.setLooping(false);
		} catch (IOException e) {}
		Egg.windowWidth = windowWidth;
		Egg.windowHeight = windowHeight;
	}

	// *********************************** LOCAL METHODS ***********************************

	public void throwEgg(VertexBufferObjectManager vertexBufferObjectManager, Scene scene, int x, int y) {
		this.scene = scene;
		spriteAnimado = new AnimatedSprite(x, y, texturaAnimada, vertexBufferObjectManager);
		final long[] DURATION_FRAME_NORMAL = { 50, 50, 50, 50, 50, 50, 50 , 50  };
		spriteAnimado.animate(DURATION_FRAME_NORMAL, 0, 7, true);
		scene.attachChild(spriteAnimado);

		final boolean leftTrueFallingFalse = x > windowWidth;
		moveModifier = null;
		if(leftTrueFallingFalse) {
			moveModifier = new MoveModifier(ON_AIR_DURATION, x, y, -100, y, this);
		} else {
			moveModifier = new MoveModifier(ON_AIR_DURATION, x, y, x, -100, this);
		}
		spriteAnimado.registerEntityModifier(moveModifier);
		new Thread(new Runnable() {
			@Override
			public void run() {
				int totalTime = 0;
				while(moveModifier != null) {
					if(leftTrueFallingFalse) {
						if(spriteAnimado.getX() < windowWidth/2)
							break;
					} else {
						if(spriteAnimado.getY() < windowHeight/2)
							break;
					}
					roomManager.throwEgg(eggId, leftTrueFallingFalse, (int)spriteAnimado.getX() + (leftTrueFallingFalse ? -300 : 0), (int)spriteAnimado.getY() + (leftTrueFallingFalse ? 0 : -225), totalTime);
					try {Thread.sleep(250);} catch (Exception e) {}
					totalTime += 250;
				}
			}
		}).start();
	}

	public boolean collide(IEntity iEntity) {
		if(iEntity != null) {
			float myX = spriteAnimado.getX();
			float myY = spriteAnimado.getY();
			float eggX = iEntity.getX();
			float eggY = iEntity.getY();
			if(Math.abs(Math.sqrt(Math.pow(myX-eggX, 2) + Math.pow(myY-eggY, 2))) < COLLIDE_DISTANCE) {
				crash();
				return true;
			}
		}
		return false;
	}

	public void crash() {
		if(moveModifier != null) {
			spriteAnimado.unregisterEntityModifier(moveModifier);
			moveModifier = null;
			eggSound.play();
			spriteAnimado.animate(CRASH_DURATION_FRAMES, CRASH_START_INDEX, CRASH_END_INDEX, false);
			new Thread(new Runnable() {
				@Override
				public void run() {
					int sendingTimes = 6;
					while(sendingTimes > 0) {
						roomManager.crashEgg(eggId, (int)spriteAnimado.getX(), (int)spriteAnimado.getY());
						try {Thread.sleep(200);} catch (InterruptedException e) {}
						sendingTimes --;
					}
					try {Thread.sleep(1000);} catch (InterruptedException e) {}
					spriteAnimado.setVisible(false);
				}
			}).start();
		}
	}

	// *********************************** LOCAL METHODS ***********************************

	// *********************************** REMOTE METHODS **********************************

	public void throwEgg(VertexBufferObjectManager vertexBufferObjectManager,Scene scene, int x, int y, final boolean leftTrueFallingFalse, int totalTime) {
		this.scene = scene;
		spriteAnimado = new AnimatedSprite(x, y, texturaAnimada, vertexBufferObjectManager);
		final long[] DURATION_FRAME_NORMAL = { 50, 50, 50, 50, 50, 50, 50 , 50  };
		spriteAnimado.animate(DURATION_FRAME_NORMAL, 0, 7, true);
		scene.attachChild(spriteAnimado);

		float duration = (ON_AIR_DURATION*1000f - totalTime)/1000f;

		moveModifier = null;
		if(leftTrueFallingFalse) {
			moveModifier = new MoveModifier(duration, x, y, -100, y, this);
		} else {
			moveModifier = new MoveModifier(duration, x, y, x, -100, this);
		}
		spriteAnimado.registerEntityModifier(moveModifier);
	}

	public void crash(int x, int y) {
		if(moveModifier != null) {
			spriteAnimado.unregisterEntityModifier(moveModifier);
			moveModifier = null;
			spriteAnimado.setX(x);
			spriteAnimado.setY(y);
			eggSound.play();
			spriteAnimado.animate(CRASH_DURATION_FRAMES, CRASH_START_INDEX, CRASH_END_INDEX, false);
			new Thread(new Runnable() {
				@Override
				public void run() {
					try {Thread.sleep(1000);} catch (InterruptedException e) {}
					spriteAnimado.setVisible(false);
				}
			}).start();
		}
	}

	// *********************************** REMOTE METHODS **********************************

	// ************************************* LISTENERS *************************************

	@Override
	public void onModifierStarted(IModifier<IEntity> pModifier, IEntity pItem) {}

	@Override
	public void onModifierFinished(IModifier<IEntity> pModifier, IEntity pItem) {
		spriteAnimado.setVisible(false);
		moveModifier = null;
		eggs.remove(this);
	}

	// ************************************* LISTENERS *************************************

	// ********************************** EQUALS AND HASH **********************************

	@Override
	public boolean equals(Object o) {
		Egg other = (Egg)o;
		return other.eggId == this.eggId;
	}

	@Override
	public int hashCode() {
		return eggId;
	}

	public IEntity getEntity() {
		return spriteAnimado;
	}

	// ********************************** EQUALS AND HASH **********************************

}
